package logger

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"net"
	"net/http"
	"os"
	"path"
	"social-app/pkg/response"
	"strings"
	"time"
)

var (
	logAddress string = "./runtime"
)

func Log() gin.HandlerFunc {
	return func(c *gin.Context) {
		if _, err := os.Stat(logAddress); os.IsNotExist(err) {
			err = os.MkdirAll(logAddress, 0777)
			if err != nil {
				panic(fmt.Errorf("create log dir '%s' error: %s", logAddress, err))
			}
		}
		timeStr := time.Now().Format(time.DateOnly)
		fileName := path.Join(logAddress, timeStr+".log")
		os.Stderr, _ = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
		//实例化
		logger := logrus.New()
		//设置输出
		logger.Out = os.Stderr
		//设置日志级别
		logger.SetLevel(logrus.InfoLevel)
		//打印方法
		logger.SetReportCaller(true)
		//设置日志格式
		logger.SetFormatter(&logrus.TextFormatter{TimestampFormat: time.DateTime})
		// 开始时间
		startTime := time.Now()
		// 处理请求
		c.Next()
		// 结束时间
		endTime := time.Now()
		// 执行时间
		latencyTime := endTime.Sub(startTime)
		method := c.Request.Method
		url := c.Request.RequestURI
		form := c.Request.PostForm.Encode()
		statusCode := c.Writer.Status()
		clientIP := c.Request.Header.Get("X-Real-IP")
		if clientIP == "" {
			clientIP = c.Request.Header.Get("X-Forwarded-For")
		}
		if clientIP == "" {
			clientIP, _, _ = net.SplitHostPort(c.Request.RemoteAddr)
		}
		if strings.Contains(clientIP, ":") {
			clientIP = strings.Split(clientIP, "%")[0]
		}
		errormessage := c.Errors.ByType(gin.ErrorTypePrivate).String()
		// 日志格式
		if len(c.Errors) > 0 {
			logger.Errorf(errormessage)
		} else {
			msg := fmt.Sprintf(" %s  %s  %s  %s  %d  %s  %s", clientIP, method, url, form, statusCode, latencyTime, errormessage)
			if statusCode == http.StatusOK {
				logger.Info(msg)
			} else {
				logger.Error(msg)
			}
		}
	}
}
func Write(msg string) {
	setOutPutFile(logrus.InfoLevel, "info")
	logrus.Info(msg)
}

func Debug(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.DebugLevel, "debug")
	logrus.WithFields(fields).Debug(args)
}

func Info(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.InfoLevel, "info")
	logrus.WithFields(fields).Info(args)
}

func Warn(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.WarnLevel, "warn")
	logrus.WithFields(fields).Warn(args)
}

// 执行完程序结束
func Fatal(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.FatalLevel, "fatal")
	logrus.WithFields(fields).Fatal(args)
}

func Error(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.ErrorLevel, "error")
	logrus.WithFields(fields).Error(args)
}

func Panic(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.PanicLevel, "panic")
	logrus.WithFields(fields).Panic(args)
}

func Trace(fields logrus.Fields, args ...interface{}) {
	setOutPutFile(logrus.TraceLevel, "trace")
	logrus.WithFields(fields).Trace(args)
}
func setOutPutFile(level logrus.Level, logName string) {
	if _, err := os.Stat(logAddress); os.IsNotExist(err) {
		err = os.MkdirAll(logAddress, 0777)
		if err != nil {
			panic(fmt.Errorf("create log dir '%s' error: %s", logAddress, err))
		}
	}

	timeStr := time.Now().Format(time.DateOnly)
	fileName := path.Join(logAddress, logName+"_"+timeStr+".log")
	var err error
	os.Stderr, err = os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
	if err != nil {
		fmt.Println("open log file err", err)
	}
	logrus.SetOutput(os.Stderr)
	logrus.SetLevel(level)
	logrus.SetFormatter(&logrus.TextFormatter{TimestampFormat: time.DateTime})
	return
}
func Recover(c *gin.Context) {
	defer func() {
		if err := recover(); err != nil {
			if _, errDir := os.Stat(logAddress); os.IsNotExist(errDir) {
				errDir = os.MkdirAll(logAddress, 0777)
				if errDir != nil {
					panic(fmt.Errorf("create log dir '%s' error: %s", logAddress, errDir))
				}
			}
			timeStr := time.Now().Format(time.DateOnly)
			fileName := path.Join(logAddress, timeStr+".log")
			f, errFile := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
			if errFile != nil {
				fmt.Println(errFile)
			}
			timeFileStr := time.Now().Format(time.DateTime)
			_, _ = f.WriteString("panic error time:" + timeFileStr + "\n")
			_, _ = f.WriteString(fmt.Sprintf("%v", err) + "\n")
			_ = f.Close()
			response.Error(c, 500, fmt.Sprintf("%v", err))
			//终止后续接口调用，不加的话recover到异常后，还会继续执行接口里后续代码
			c.Abort()
		}
	}()
	c.Next()
}
